home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / Libraries / PlayerPRO 4.4.1 / Filters Plugs / Mix.c < prev    next >
C/C++ Source or Header  |  1995-04-16  |  9KB  |  347 lines

  1. /*    Mix                */
  2. /*    v 0.2            */
  3. /*    1995 by Liane    */
  4.  
  5. //    Usage:
  6. //    Digital mixing of two sounds.
  7. //    The sound in the clipboard (get it by Copy) is
  8. //    mixed with the one opened, beginning at the
  9. //    start of the selection.
  10. //    The sound is extended as needed, and Normalize
  11. //    is applied to avoid clipping.
  12. //
  13. //    WARNING
  14. //    This plug does work ONLY with 8 bits data
  15.  
  16. #include <A4Stuff.h>
  17. #include <SetUpA4.h>
  18. #include <Sound.h>
  19. #include "MAD.h"
  20. #include "PPPlug.h"
  21.  
  22. #if defined(powerc) || defined(__powerc)
  23. enum {
  24.         PlayerPROPlug = kCStackBased
  25.         | RESULT_SIZE(SIZE_CODE( sizeof(OSErr)))
  26.         | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof( Ptr*)))
  27.         | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof( struct FileInstrData*)))
  28.         | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof( long)))
  29.         | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof( long)))
  30.         | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof( PPInfoPlug*)))
  31. };
  32.  
  33. ProcInfoType __procinfo = PlayerPROPlug;
  34. #else
  35. #include <A4Stuff.h>
  36. #endif
  37.  
  38.  
  39. typedef short    *shortPtr;
  40. typedef long    *longPtr;
  41.  
  42. #define enclosure    9
  43. #define sname1        3
  44. #define sname2        4
  45. #define slider1        5
  46. #define slider2        6
  47.  
  48. static long gp1;
  49. static long gp2;
  50.  
  51. #define min(a,b) (((a) < (b)) ? (a) : (b))
  52. #define max(a,b) (((a) > (b)) ? (a) : (b))
  53.  
  54. pascal OSErr SetDialogDefaultItem (    DialogPtr    theDialog,
  55.                                     short        newItem)
  56.     = {0x303c,0x0304,0xAA68};
  57.  
  58. void raiseRect (Rect theRect)
  59. {
  60.     ForeColor(whiteColor);
  61.     MoveTo(theRect.left,theRect.bottom);
  62.     LineTo(theRect.left,theRect.top);
  63.     LineTo(theRect.right,theRect.top);
  64.     ForeColor(blackColor);
  65.     LineTo(theRect.right,theRect.bottom);
  66.     LineTo(theRect.left,theRect.bottom);
  67. }
  68.  
  69. void groundRect (Rect theRect)
  70. {
  71.     ForeColor(whiteColor);
  72.     MoveTo(theRect.right,theRect.top);
  73.     LineTo(theRect.right,theRect.bottom);
  74.     LineTo(theRect.left,theRect.bottom);
  75.     ForeColor(blackColor);
  76.     LineTo(theRect.left,theRect.top);
  77.     LineTo(theRect.right,theRect.top);
  78. }
  79.  
  80. void drawSlider (    Rect    theRect,
  81.                     long    theValue)
  82. {
  83. short    iWidth;
  84. Str255    s;
  85.  
  86.     groundRect(theRect);
  87.     theRect.left += 1;
  88.     theRect.top += 1;
  89.     {
  90.     Pattern    myPat = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
  91.     iWidth = theRect.left; // save left
  92.     theRect.left = theRect.left + (((theRect.right - theRect.left) * theValue) / 100);
  93.     EraseRect(&theRect);
  94.     theRect.right = theRect.left;
  95.     theRect.left = iWidth;
  96.     ForeColor(greenColor);
  97.     FillRect(&theRect,&myPat);
  98.     }
  99.     
  100.     ForeColor(blackColor);
  101.     NumToString(theValue, s);
  102.     TextFont(geneva);
  103.     TextSize(9);
  104.     SetRect(&theRect,theRect.left - 20,theRect.top,theRect.left - 1,theRect.bottom - 4);
  105.     EraseRect(&theRect);
  106.     iWidth = TextWidth(&s[1],0,s[0]);
  107.     MoveTo(theRect.right - iWidth - 2,theRect.bottom);
  108.     DrawString(s);
  109.     TextFont(systemFont);
  110.     TextSize(12);
  111. }
  112.  
  113. pascal void xRectProc (WindowPtr    theWindow,
  114.                         short        theItem)
  115. {
  116. short    iType;
  117. Handle    iHandle;
  118. Rect    iRect;
  119.  
  120.     GetDItem(theWindow,theItem,&iType,&iHandle,&iRect);
  121.     raiseRect( iRect);
  122. }
  123.  
  124. pascal void sliderProc (WindowPtr    theWindow,
  125.                         short        theItem)
  126. {
  127. short    iType;
  128. Handle    iHandle;
  129. Rect    iRect;
  130. long    v;
  131.  
  132.     long oldA4 = SetUpA4 ();
  133.  
  134.     if (theItem == slider1) v = gp1;
  135.     else v = gp2;
  136.  
  137.     GetDItem(theWindow,theItem,&iType,&iHandle,&iRect);
  138.     drawSlider( iRect, v);
  139.  
  140.     RestoreA4(oldA4);
  141. }
  142.  
  143. GDHandle    TheGDevice:0xCC8;
  144.  
  145. void AutoPosition( DialogPtr aDia)
  146. {
  147.     Point    Position, mouse;
  148.     Rect    ViewRect;
  149.     short    XSize = (aDia->portRect.right - aDia->portRect.left), YSize = (aDia->portRect.bottom - aDia->portRect.top);
  150.  
  151.  
  152.     GetMouse( &mouse);
  153.     LocalToGlobal( &mouse);
  154.  
  155.     SetRect( &ViewRect, (*TheGDevice)->gdRect.left + 8, (*TheGDevice)->gdRect.top + 43,
  156.                         (*TheGDevice)->gdRect.right - 8, (*TheGDevice)->gdRect.bottom - 8);
  157.  
  158.     Position.h = mouse.h - XSize/2;
  159.     if( Position.h + XSize >= ViewRect.right) Position.h = ViewRect.right - XSize;
  160.     else if( Position.h <= ViewRect.left) Position.h = ViewRect.left;
  161.  
  162.     Position.v = mouse.v - YSize/2;
  163.     if( Position.v + YSize >= ViewRect.bottom) Position.v = ViewRect.bottom - YSize;
  164.     else if( Position.v <= ViewRect.top) Position.v = ViewRect.top;
  165.  
  166.     MoveWindow( aDia, Position.h, Position.v, false);
  167.  
  168.     ShowWindow( aDia);
  169. }
  170.  
  171.  
  172. Boolean getParams ( short dlgID, Str255 s1, Str255 s2, PPInfoPlug *thePPInfoPlug)
  173. {
  174. DialogPtr    theDialog;
  175. Boolean        theResult = false;
  176.  
  177.     theDialog = GetNewDialog(dlgID,nil,(WindowPtr)-1);
  178.     if (theDialog) {
  179.         short    iType, itemHit;
  180.         Handle    iHandle;
  181.         Rect    iRect;
  182.         
  183.         SetPort( theDialog);
  184.         AutoPosition( theDialog);
  185.         GetDItem(theDialog,sname1,&iType,&iHandle,&iRect);
  186.         SetIText(iHandle,s1);
  187.         GetDItem(theDialog,sname2,&iType,&iHandle,&iRect);
  188.         SetIText(iHandle,s2);
  189.         GetDItem(theDialog,slider1,&iType,&iHandle,&iRect);
  190.         SetDItem(theDialog,slider1,iType,(Handle)sliderProc,&iRect);
  191.         GetDItem(theDialog,slider2,&iType,&iHandle,&iRect);
  192.         SetDItem(theDialog,slider2,iType,(Handle)sliderProc,&iRect);
  193.         GetDItem(theDialog,enclosure,&iType,&iHandle,&iRect);
  194.         SetDItem(theDialog,enclosure,iType,(Handle)xRectProc,&iRect);
  195.  
  196.         do {
  197.             ModalDialog( (ModalFilterProcPtr) thePPInfoPlug->MyDlgFilterUPP, &itemHit);
  198.             if ((itemHit == slider1) || (itemHit == slider2))
  199.             {    //track slider
  200.                 GrafPtr    savePort;
  201.                 Point    newp, oldp = { 0, 0};
  202.                 GetPort(&savePort);
  203.                 SetPort(theDialog);
  204.                 GetDItem(theDialog,itemHit,&iType,&iHandle,&iRect);
  205.                 while(WaitMouseUp()) {
  206.                     GetMouse(&newp);
  207.                     if (DeltaPoint(oldp,newp) & 0xFFFF) {
  208.                         long newVal = min( 100, max( 0, ((newp.h - iRect.left) * 100) / (iRect.right - iRect.left)));
  209.                         if (itemHit == slider1) gp1 = newVal;
  210.                         else gp2 = newVal;
  211.                         drawSlider( iRect, newVal);
  212.                         oldp = newp;
  213.                     }
  214.                 }
  215.                 SetPort(savePort);
  216.             }
  217.         } while ((itemHit != ok) && (itemHit != cancel));
  218.         if (itemHit == ok) {
  219.             theResult = true;
  220.         }
  221.         DisposDialog(theDialog);
  222.     }
  223.     return theResult;
  224. }
  225.  
  226. void alertUser ( short errString)
  227. {
  228. Str255    s;
  229.     GetIndString(s,5010,errString);
  230.     ParamText(s,nil,nil,nil);
  231.     StopAlert(5011,nil);
  232. }
  233.  
  234. OSErr main(     Ptr                        *InstrumentPtr,
  235.                 struct FileInstrData    *theData,
  236.                 long                    SelectionStart,
  237.                 long                    SelectionEnd,
  238.                 PPInfoPlug                *thePPInfoPlug)
  239. {
  240.     long    oldA4, scrapOffset;
  241.     Handle    aHandle;
  242.  
  243.     oldA4 = SetCurrentA4();
  244.     RememberA4();
  245.     aHandle = nil;
  246.     if (GetScrap(aHandle,soundListRsrc,&scrapOffset) > 0) {
  247.         Str255    s1, s2 = "\pUntitled";
  248.  
  249.         aHandle = NewHandle(0);
  250.         s1[0] = strlen(theData->Filename);
  251.         BlockMove(theData->Filename,&s1[1],s1[0]);
  252.         if (GetScrap(aHandle,'STR ',&scrapOffset) > 0)
  253.             BlockMove(*aHandle,&s2,**aHandle + 1);
  254.         
  255.         gp1 = 50;
  256.         gp2 = 50;
  257.  
  258.         if (getParams (5010, s1, s2, thePPInfoPlug)) {
  259.             long    i, length1, length2, resultLength,
  260.                     temp1, temp2;
  261.             Ptr        clipPtr, resultPtr;
  262.  
  263.             GetScrap(aHandle,soundListRsrc,&scrapOffset);    //get the sound
  264.             HLockHi(aHandle);
  265.             
  266.             clipPtr = *aHandle;
  267.             i = *(shortPtr)clipPtr;
  268.             clipPtr += 4;
  269.             if ((i == 1) || (i == 2)) {
  270.                 if ((i == 2) || (*(shortPtr)clipPtr == sampledSynth)) {
  271.                     Ptr        worgPtr, wclipPtr, wresultPtr;
  272.                     long    temp, peak = 0;
  273.  
  274.                     if (i == 1) {
  275.                         clipPtr += 20;
  276.                     } else  clipPtr += 18;
  277.                     length2 = *(longPtr)clipPtr;    // sample length
  278.                     clipPtr += 18;                    // points to sample data
  279.     
  280.                     length1 = theData->insSize - SelectionStart;
  281.                     
  282.                     resultLength = SelectionStart + max( length1, length2);
  283.                     resultPtr = NewPtr(resultLength);
  284.  
  285.                     worgPtr = *InstrumentPtr; wclipPtr = clipPtr;
  286.                     for( i = 0; i < SelectionStart; i++) // first pass to get max value.
  287.                     {
  288.                         temp1 = *worgPtr++;
  289.                         peak = max( peak, labs( gp1 * temp1));
  290.                     }
  291.                     for( i = 0; i < (resultLength - SelectionStart); i++)
  292.                     {
  293.                         if (i < length1) {
  294.                             temp1 = *worgPtr;
  295.                         } else temp1 = 0;
  296.                         if (i < length2) {
  297.                             temp2 = (*wclipPtr & 0xFF) - 0x80;
  298.                         } else temp2 = 0;
  299.                         
  300.                         peak = max( peak, labs((gp1 * temp1) + (gp2 * temp2)));
  301.                             
  302.                         worgPtr++;
  303.                         wclipPtr++;
  304.                     }
  305.                     
  306.                     peak = ((long)0x80 * 0x10000) / peak;
  307.                     
  308.                     worgPtr = *InstrumentPtr; wclipPtr = clipPtr - SelectionStart; wresultPtr = resultPtr;
  309.                     for( i = 0; i < resultLength; i++) // one more time, all together, now !!!
  310.                     {
  311.                         if (i < theData->insSize) {
  312.                             temp1 = *worgPtr;
  313.                         } else temp1 = 0;
  314.                         if ((i >= SelectionStart) && (i < (length2 + SelectionStart))) {
  315.                             temp2 = (*wclipPtr & 0xFF) - 0x80;
  316.                         } else temp2 = 0;
  317.                         
  318.                         temp = (gp1 * temp1) + (gp2 * temp2);
  319.                         temp = (peak * temp) / 0x10000;
  320.                             
  321.                         if( temp >= 127) temp = 127;    // overflow ?
  322.                         else if( temp <= -128 ) temp = -128;
  323.  
  324.                         *wresultPtr = temp;
  325.                         worgPtr++;
  326.                         wclipPtr++;
  327.                         wresultPtr++;
  328.                     }
  329.                     
  330.                     DisposPtr(*InstrumentPtr);            //all done
  331.                     *InstrumentPtr = resultPtr;            //now switch
  332.                     theData->insSize = resultLength;    //Instrument Ptr
  333.                 
  334.                 } else alertUser (3);
  335.             } else alertUser (2);
  336.             
  337.             HUnlock(aHandle);
  338.         
  339.         }
  340.         
  341.         DisposHandle(aHandle);
  342.         
  343.     } else alertUser (1);
  344.  
  345.     SetA4(oldA4);
  346.     return noErr;
  347. }